home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 80 / CD Actual 80 Julio-Agosto 2003.iso / Linux / LinuxGazette / lg / issue91 / misc / mathew / code / vpx322xd.c < prev   
Encoding:
C/C++ Source or Header  |  2003-05-20  |  16.3 KB  |  739 lines

  1. /*  Micronas vpx 3224D/3225D video processor i2c device driver. 
  2.     Copyright Cherry George Mathew <cherry@freeshell.org>
  3.     
  4.     Based on Frodo Looijaard's <frodol@dds.nl> document on
  5.     writing i2c clients. See Documentation/i2c/writing-clients.
  6.     
  7.     Special thanks to the i2c authors for excellent code templates and
  8.     useful documentation.
  9.     
  10. */
  11.  
  12. /*  This program is free software; you can redistribute it and/or modify
  13.     it under the terms of the GNU General Public License as published by
  14.     the Free Software Foundation; either version 2 of the License, or
  15.     (at your option) any later version.
  16.     
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.     
  22.     You should have received a copy of the GNU General Public License
  23.     along with this program; if not, write to the Free Software
  24.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. */
  26.  
  27. /* #include <linux/version.h>  */
  28. #include <linux/module.h>
  29. #include <linux/pci.h>
  30. #include <linux/i2c.h>
  31. #include <linux/init.h> 
  32. #include <linux/spinlock.h>   
  33. #include <linux/byteorder/generic.h>
  34. #include <linux/byteorder/swab.h>
  35. #include <linux/sched.h> 
  36. #include <linux/videodev.h>
  37. #include <asm/io.h>
  38. #include <asm/bitops.h>
  39. #include "pvcard.h"
  40. #include "pvproc.h"
  41.  
  42. /* Module params. */
  43. static int debug;
  44.  
  45. /* Functional level debugging */
  46. #define dprintk(fmt, args...) if (debug>=1) printk(KERN_DEBUG "pvcl-debug: " fmt, ## args);
  47. /* Debugging single functions */
  48. #define tprintk(fmt, args...) if (debug>=2) printk(KERN_DEBUG "pvcl-debug: " fmt, ## args);
  49. /* Warning - too verbose. Debugging port conversations. */
  50. #define vprintk(fmt, args...) if (debug>=3) printk(KERN_DEBUG "pvcl-debug:" fmt, ## args);
  51.  
  52.  
  53. /* module parameters: 
  54.  */
  55.  
  56. const char *client_name = "vpx i2c bus interface"; 
  57. static int re_entry = 0;
  58.  
  59. /* currently, vmode is the only "sticky" status variable in vpx.
  60.  * Oh, yes, and vpx_client.
  61.  */
  62. static __u16 vmode;
  63.  
  64. /* This client pointer contains the address of a detected vpx chip, if any.
  65.  * Multiple chips, are unlikely on the same adapter, and are ignored. 
  66.  * In such cases, the chip with a lower I2C address is detected.
  67.  */
  68.  
  69. static struct i2c_client * vpx_client;
  70.  
  71.  
  72. int vpx_init_client(struct i2c_client *client);
  73. int vpx_attach_adapter(struct i2c_adapter *adapter);
  74. int vpx_detach_client(struct i2c_client *client);
  75. int vpx_command(struct i2c_client *client, unsigned int cmd, void *arg);
  76. void vpx_inc_use(struct i2c_client *client);
  77. void vpx_dec_use(struct i2c_client *client);
  78. void vpx_poll_fp_busy(struct i2c_client *client);
  79.  
  80. /* TODO: Clearup I2C_DRIVERID_EXP0 issue on the v4l list. */
  81.  
  82. struct i2c_driver vpx_driver =
  83. {  
  84.     name:              "Micronas vpx 3224/5d i2c driver",
  85.     id:                I2C_DRIVERID_EXP0,
  86.     flags:             I2C_DF_NOTIFY,
  87.     attach_adapter:    &vpx_attach_adapter,
  88.     detach_client:     &vpx_detach_client,
  89.     command:           &vpx_command,   
  90.     inc_use:           &vpx_inc_use,   
  91.     dec_use:           &vpx_dec_use    
  92. };
  93.  
  94.  
  95.  
  96.  
  97. /* Scan ports 0x43 - 0x47 (7-bit addresses) for the vpx */
  98.  
  99. static unsigned short normal_i2c[] = { I2C_CLIENT_END };
  100.  
  101. static unsigned short normal_i2c_range[] = { 0x43, 0x47, I2C_CLIENT_END };
  102.  
  103. /* Magic definition of all other variables and things */
  104. I2C_CLIENT_INSMOD;
  105.  
  106.  
  107. /* byte banging routines. i2c-algo-bit.c (lines 363 - 364 assumes data
  108.    to be little endian. Am I right or have I read the code wrong ?
  109. */
  110.  
  111.  
  112. s32 vpx_read_byte(struct i2c_client *client, u8 reg)
  113. {
  114.       /* byte-sized register */
  115.     return i2c_smbus_read_byte_data(client,reg);
  116. }
  117.  
  118. s32 vpx_read_word(struct i2c_client *client, u8 reg)
  119. {
  120.     /* word-sized register */
  121.     
  122. #ifdef __LITTLE_ENDIAN
  123.     /* The vpx takes MSB first. OK. topsy turvy! */
  124.     
  125.     return swab16(i2c_smbus_read_word_data(client,reg));
  126.  
  127. #endif
  128.  
  129.     return i2c_smbus_read_word_data(client,reg);
  130. }
  131.  
  132. s32 vpx_write_byte(struct i2c_client *client, u8 reg, u16 value)
  133. {
  134.     
  135.     /* byte-sized register */
  136.       return i2c_smbus_write_byte_data(client,reg,value);
  137.       
  138. }
  139.  
  140. s32 vpx_write_word(struct i2c_client *client, u8 reg, u16 value)
  141. {
  142.     /* word-sized register */
  143.     /* Do the byte swap */
  144.  
  145. #ifdef __LITTLE_ENDIAN
  146.  
  147.     value=swab16(value);
  148.  
  149. #endif
  150.     return i2c_smbus_write_word_data(client,reg,value);
  151. }
  152.  
  153.  
  154. s32 vpx_fp_write(struct i2c_client *client, u16 fp_reg, u16 value)
  155. {
  156.     int status;
  157.     vpx_poll_fp_busy(client);
  158.     if((status=vpx_write_word(client, FPWR, fp_reg))) return status;
  159.     vpx_poll_fp_busy(client);
  160.      return vpx_write_word(client, FPDAT, (value & 0x3fff)); 
  161. }
  162.  
  163. s32 vpx_fp_read(struct i2c_client *client, u16 fp_reg)
  164. {
  165.         s32 status;
  166.         vpx_poll_fp_busy(client);
  167.         if((status=vpx_write_word(client, FPRD, fp_reg))) return status;
  168.         vpx_poll_fp_busy(client);
  169.          return (0x3fff & vpx_read_word(client, FPDAT)); 
  170. }
  171.  
  172. void vpx_poll_fp_busy(struct i2c_client *client)
  173. {
  174.  
  175.     unsigned long status;
  176.     status = (unsigned long) vpx_read_byte(client, FPSTA);
  177.     while(test_bit(2, &status))
  178.         {
  179.             status = (unsigned long) vpx_read_byte(client, FPSTA);
  180.             
  181.             /* This is a half hearted attempt to sleep 
  182.              * for 20 milliseconds. The vpx manual says that if 
  183.              * the onboard FP (FP stands for 
  184.              * "Fast Processor" :-O ) is busy, read/write
  185.              * to it needs to be retried after 20ms.
  186.              * The priority here is for other processes 
  187.              * to run. Not for us to encourage 
  188.              * couch potatoes... ;)
  189.              */
  190.             
  191.             set_current_state(TASK_UNINTERRUPTIBLE);
  192.             schedule_timeout(VPX_BUSY_TIMEOUT);
  193.         }
  194.     
  195. }    
  196.  
  197.                 
  198. /* vpx functional layer */
  199.  
  200. /* initialize the video processor */
  201.  
  202. void vpx_pinit(struct i2c_client *client, int model)
  203. {
  204.     int portword;
  205.     /* I've gone to the trouble of customizing vpx parameters here
  206.      * with extensibility in mind. For each card, there should be a 
  207.      * special set of settings for the vpx.
  208.      */ 
  209.  
  210.     switch(model)
  211.         {
  212.         case PVCLPP_COMBO:
  213.             /* The pvclpp combo card uses a philips TEA5582
  214.              * FM demodulator to demodulate sound.
  215.              * The TEA5582 has a mute control, which is connected
  216.              * via VPort B, bit 1. Therefore, we have to guess that
  217.              * the video capture takes place via the 8bits of
  218.              * VPort A. This is set via FPreg, 0x154. 
  219.              */
  220.  
  221.             portword = vpx_fp_read(client, 0x154) | 0x302;
  222.             tprintk("Writing %04x to FPreg 0x154 \n.",
  223.                 portword);
  224.             
  225.             vpx_fp_write(client, 0x154, portword);
  226.             
  227.  
  228.             /* Set VPort Driver strength. 
  229.              * Got this from the default setting of the pvclpp 
  230.              * application (tvtap) for win98. Booted into 
  231.              * windows, ran tvtap, killed it with softice,
  232.              * warm booted into linux through int 19, 
  233.              * and read the I2C 
  234.              * registers. 
  235.              */
  236.             
  237.             vpx_write_byte(client, 0xf9, 0x24);
  238.             vpx_write_byte(client, 0xf8, 0x24);
  239.             
  240.             /* VREF pulse width = 6. 
  241.              * Guess how I found out ?? ;-)
  242.              */
  243.             
  244.             vpx_fp_write(client, 0x153, 0x20);
  245.  
  246.             /* Set the input source. There are 3 input 
  247.              * sources, VIN1, VIN2, VIN3.
  248.              * FPReg(0x21) [1:0] determines 
  249.              * hardcoding to television tuner input 
  250.              * for just now. */
  251.  
  252.             portword = vpx_fp_read(client, 0x21) & 0xfc;
  253.  
  254.             vpx_fp_write(client, 0x21, portword | 0x01);
  255.  
  256.         }
  257.  
  258.     /* Disable Winload table #2. We use Winload table #1 for both fields.*/
  259.  
  260.     vpx_fp_write(client, 0x12B, 0xc00);
  261.     
  262.     /* Latch current Values */
  263.     portword = vpx_fp_read(client, 0x140);
  264.     portword |= 0x40;
  265.     vpx_fp_write(client, 0x140, portword);
  266.  
  267.  
  268.     /* Switch off slicer. */
  269.     vpx_write_byte(client, 0xaa, 0x40);
  270.     
  271.     tprintk("I2C reg. 0xAA reads %02x. \n", 
  272.         vpx_read_byte(client, 0xaa));
  273.     
  274.  
  275.     
  276.     /* Set to PAL - B, G, H, I (50Hz) for testing on my VCR.
  277.      * Here is the vpx manual listing for setting various standards. 
  278.      *
  279.      * FPReg(0x20) [2:0]         Standard    Vert.       IF. (MHz)
  280.      *             0          PAL B,G,H,I    50Hz         4.433618
  281.      *             1               NTSC M    60Hz         3.579545
  282.      *             2                SECAM    50Hz         4.286
  283.      *             3               NTSC44    60Hz         4.433618
  284.      *             4                PAL M    60Hz         3.575611
  285.      *             5                PAL N    50Hz         3.582056
  286.      *             6               PAL 60    60Hz         4.433618
  287.      *             7            NTSC COMB    60Hz         3.579545
  288.      */
  289.  
  290.  
  291.      portword = vpx_fp_read(client, 0x20) & 0xff8; 
  292.  
  293.      vpx_fp_write(client, 0x20, portword | 0x00); 
  294.     
  295.     /* There's some confusion in the ITU 601 format. Cr and Cb get
  296.      * Swapped. Let's re-swap them.
  297.      */
  298.  
  299.     portword = vpx_fp_read(client, 0x126) & 0xeff;
  300.  
  301.     vpx_fp_write(client, 0x126, portword | 0x100);
  302.  
  303.  
  304. }
  305.  
  306.  
  307.  
  308. void vpx_start_capture(struct i2c_client *client)
  309. {
  310.     int portword;
  311.     
  312.  
  313.     /* Enable VPortA, VPortB, Pixclk, HREF, VREF, FIELD, VACT, LLC, LLC2 */
  314.     
  315.     portword = vpx_read_byte(client, 0xf2) & 0xf0;
  316.     portword |= 0x0f;
  317.     
  318.     vpx_write_byte(client, 0xf2, portword);
  319. }
  320.  
  321. void vpx_stop_capture(struct i2c_client *client)
  322. {
  323.     int portword;
  324.     
  325.     /* Disable VPortA, VPortB, Pixclk, 
  326.        HREF, VREF, FIELD, VACT, LLC, LLC2 */
  327.     
  328.     portword = vpx_read_byte(client, 0xf2) & 0xf0;
  329.     
  330.     vpx_write_byte(client, 0xf2, portword);
  331. }
  332.  
  333. void vpx_set_window(struct i2c_client *client, struct video_window *vwin)
  334. {
  335.     /* Winloadtab1 is loaded here. It is active for both fields.
  336.      */
  337.  
  338.     int portword;
  339.     
  340.     switch(vmode)
  341.         {
  342.         case VIDEO_MODE_PAL: {
  343.                         
  344.             /* Vertical Begin Scanline */
  345.             vpx_fp_write(client, 0x120, 20);
  346.  
  347.             /* Horizontal Begin, Pixel */
  348.             vpx_fp_write(client, 0x123, 5);
  349.  
  350.             /* Maximum Lines input 310:  PAL is a 625 line s/m. */
  351.             vpx_fp_write(client, 0x121, 305);
  352.             
  353.             /* Scaled number of Vertical Lines. */
  354.             vwin->height = 
  355.                 (vwin->height > 305 ? 
  356.                  300 : vwin->height) & 0x1ff;
  357.  
  358.             vwin->height =
  359.                 vwin->height < 24 ?
  360.                 24 : vwin->height;
  361.  
  362.             /* Scaled Width of raster line. */
  363.             vwin->width = 
  364.                 (vwin->width > 800 ? 
  365.                  800 : vwin->width) & 0x7ff;
  366.  
  367.             vwin->width = vwin->width < 32 ? 
  368.                 32 : vwin->width;
  369.  
  370.             break;
  371.         }            
  372.  
  373.         default:
  374.             return;
  375.         }
  376.  
  377.     /* Update No. of Vlines to vpx */
  378.  
  379.     vpx_fp_write(client, 0x122, vwin->height);
  380.  
  381.     /* Width of raster, upto 800 pixels */
  382.  
  383.     vpx_fp_write(client, 0x125, vwin->width);
  384.     vpx_fp_write(client, 0x124, vwin->width);
  385.  
  386.  
  387.     /* Latch current Values */
  388.     portword = vpx_fp_read(client, 0x140);
  389.     portword |= 0x20;
  390.     vpx_fp_write(client, 0x140, portword);
  391.  
  392.  
  393. }
  394.  
  395.  
  396. void vpx_set_picture(struct i2c_client *client, struct video_picture *vpict)
  397. {
  398.     
  399.     int portword;
  400.     
  401.     tprintk("Brightness: %d, Contrast: %d, Colour: %d, Hue %d \n",
  402.            vpict->brightness, vpict->contrast, vpict->colour,
  403.            vpict->hue);
  404.  
  405.     /* set contrast FPReg 0x132 [5].[4:0] = contrast ratio */    
  406.  
  407.            portword = vpx_fp_read(client, 0x132) & 0xfd0;
  408.  
  409.     portword |= (vpict->contrast >> 10) & 0x3f;
  410.  
  411.     vpx_fp_write(client, 0x132, portword);
  412.  
  413.     tprintk("H/W contrast set to %d.%d \n", vpict->contrast >> 15,
  414.         vpict->contrast >> 11 & 0x1f);
  415.  
  416.     /* Set Brightness */
  417.     portword = vpx_fp_read(client, 0x131) & 0xf00;
  418.  
  419.     portword |= vpict->brightness >> 8;
  420.  
  421.     vpx_fp_write(client, 0x131, portword);
  422.     
  423.     
  424.  
  425.  
  426. }
  427.  
  428. int vpx_detect_client(struct i2c_adapter *adapter, int address, 
  429.               unsigned short flags, int kind)
  430. {
  431.     int err = 0;
  432.  
  433.     struct i2c_client *new_client;
  434.  
  435.     dprintk("in vpx_detect_client() \n");
  436.     
  437.     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_EMUL)){
  438.         return 0;
  439.     }
  440.         
  441.        
  442.     if(! (new_client = 
  443.             kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) {
  444.             
  445.         return -ENOMEM;
  446.     }
  447.  
  448.     new_client->addr = address;
  449.     new_client->adapter = adapter;
  450.     new_client->driver = &vpx_driver;
  451.     new_client->flags = 0;
  452.     
  453.     /* Now, we do the remaining detection. No `force' parameter is used. */
  454.             
  455.     if (vpx_read_byte(new_client, VPX_REG_JEDEC) != VPX_JEDEC_ID)
  456.         {
  457.             goto BAILOUT;
  458.         }
  459.     if (vpx_read_byte(new_client, VPX_REG_PARTNUM1) != VPX_PARTNUM1_ID)
  460.         {
  461.             goto BAILOUT;
  462.         }
  463.     
  464.     if ((vpx_read_byte(new_client, VPX_REG_PARTNUM0) == VPX_3224D_ID)){
  465.         
  466.         printk( KERN_INFO 
  467.             "vpx: Found: vpx 3224d chip @ 0x%02x \n", 
  468.             (new_client->addr << 1) );
  469.     
  470.         if((err=vpx_init_client(new_client))) goto BAILOUT;
  471.         return 0;
  472.     }
  473.     
  474.     if (vpx_read_byte(new_client, 
  475.               VPX_REG_PARTNUM0) == VPX_3225D_ID){
  476.         printk( KERN_INFO
  477.             "vpx: Found: vpx 3225d chip @ 0x%02x \n", 
  478.             (new_client->addr << 1));
  479.  
  480.         if((err=vpx_init_client(new_client))) goto BAILOUT;
  481.         return 0;
  482.     }
  483.     else{
  484.         printk( KERN_WARNING
  485.             "vpx:  Can't find supported vpx chip 
  486.                                on this adapter. Sorry.\n");        
  487.  
  488.  
  489.         goto BAILOUT;
  490.     }
  491.     
  492.  
  493.  BAILOUT:    
  494.     kfree(new_client);
  495.     return err; 
  496.     
  497. }
  498.  
  499.  
  500.  
  501. int vpx_init_client(struct i2c_client *client)
  502. {
  503.     
  504.     int err=0;
  505.  
  506.  
  507.     /* This driver is non re-entrant; ie; can only support one chip 
  508.        at a time.
  509.     */
  510.  
  511.     if(re_entry) 
  512.         {
  513.             printk(KERN_INFO
  514.                    "Sorry, only one client allowed per adapter. \n");
  515.             return -EBUSY;
  516.         }
  517.     
  518.     re_entry = 1;
  519.  
  520.     /* Fill in the remaining client fields. */
  521.     strcpy(client->name, client_name);
  522.     
  523.     
  524.     /* Tell the i2c layer a new client has arrived */
  525.     
  526.     if ((err = i2c_attach_client(client)))
  527.         {
  528.             return err;    
  529.         }
  530.  
  531.     /* Finally link this one client with our global client pointer */
  532.     vpx_client = client;
  533.  
  534.     return 0;
  535. }
  536.  
  537.     
  538.  
  539. int vpx_detach_client(struct i2c_client *client)
  540. {
  541.     int err;
  542.     
  543.     
  544.     /* Try to detach the client from i2c space */
  545.     if ((err = i2c_detach_client(client))) {
  546.         printk("vpx322xd: Client deregistration failed, client not detached.\n");
  547.  
  548.         return err;
  549.     }
  550.  
  551.     re_entry=0;
  552.  
  553.     MOD_DEC_USE_COUNT;
  554.  
  555.     /* Frees client data too, if allocated at the same time */
  556.     kfree(client); 
  557.     return 0;
  558. }
  559.  
  560. int vpx_command(struct i2c_client *client, unsigned int cmd, void *arg)
  561. {
  562.     /* Please note that it is the caller's responsibility to 
  563.      * maintain state information about the video processor. 
  564.      * The only VPROC_GET command is
  565.      * used to query the video standard. ie; PAL, NTSC and such.
  566.      */
  567.  
  568.     switch(cmd)
  569.         {
  570.         case VPROC_INIT:
  571.             {
  572.                 int model = * ((int *) arg);
  573.  
  574.                 vpx_pinit(client, model);
  575.                 dprintk("VPROC_INIT called. \n");
  576.                 break;
  577.             }
  578.  
  579.         case VPROC_START_CAPTURE:
  580.             
  581.             vpx_start_capture(client);
  582.  
  583.             dprintk("VPROC_START_CAPTURE called. \n");
  584.             break;
  585.             
  586.             
  587.         case VPROC_STOP_CAPTURE:
  588.             
  589.             vpx_stop_capture(client);
  590.             
  591.             dprintk("VPROC_STOP_CAPTURE called. \n");
  592.             break;
  593.             
  594.             
  595.         case VPROC_SET_CAP_MODE:
  596.             
  597.             /* SET to PAL/NTSC/SECAM via struct */
  598.             vmode = *((int *)(arg));
  599.             dprintk("VPROC_SET_CAP_MODE called. \n");    
  600.             break;
  601.             
  602.  
  603.         case VPROC_GET_CAP_MODE:
  604.             memcpy(arg, &vmode, sizeof(int));
  605.             break;
  606.             
  607.         case VPROC_SET_WINDOW:
  608.             {
  609.                 struct video_window * vwin = arg;
  610.                 vpx_set_window(client, vwin);
  611.                 dprintk("VPROC_SET_WINDOW called. \n");
  612.                 break;
  613.             }
  614.             
  615.         case VPROC_SET_PICTURE:
  616.             {
  617.                 struct video_picture * vpict = arg;
  618.                 vpx_set_picture(client, vpict);
  619.                 dprintk("VPROC_SET_PICTURE called. \n");
  620.                 break;
  621.             }
  622.         }
  623.     
  624.     
  625.     return 0;
  626. }
  627.  
  628. int vpx_attach_adapter(struct i2c_adapter *adapter)
  629. {
  630.     int retval;
  631.     switch ((adapter->id & I2C_ALGO_BIT)) {
  632.     case I2C_ALGO_BIT:
  633.  
  634.         printk(KERN_INFO "vpx: probing i2c adapter %s ... \n",
  635.                adapter->name);
  636.         retval = i2c_probe(adapter,&addr_data,&vpx_detect_client);
  637.  
  638.         break;
  639.  
  640.     default:
  641.  
  642.         printk("vpx: skipping adapter %s, 
  643.                             adapter type not supported.\n",
  644.                adapter->name);
  645.         retval = 0;
  646.     }
  647.  
  648.     /* Had to put this here because of messy code in vpx_detect_client()
  649.      * TODO: Cleanup the chip detect code in vpx_detect_client().
  650.      */
  651.  
  652.     if(!retval) 
  653.         MOD_INC_USE_COUNT;
  654.  
  655.     return retval;
  656.  
  657. }
  658.  
  659. void vpx_inc_use(struct i2c_client *client)
  660. {
  661.     MOD_INC_USE_COUNT;
  662. }
  663.  
  664. void vpx_dec_use(struct i2c_client *client)
  665. {
  666.     MOD_DEC_USE_COUNT;
  667. }
  668.  
  669.  
  670.  
  671.  
  672. int __init vpx_init(void)
  673. {
  674.     int res;
  675.     printk("vpx version %s (%s)\n", VPX_VERSION, VPX_DATE);
  676.     
  677.     if ((res = i2c_add_driver(&vpx_driver))) {
  678.         printk("vpx: Driver registration failed, module not inserted.\n");
  679.         return res;
  680.     }
  681.  
  682.     return 0;
  683. }
  684.  
  685. int __init vpx_cleanup(void)
  686. {
  687.     int res;
  688.     if ((res = i2c_del_driver(&vpx_driver))) {
  689.         printk("vpx: Driver de-registration failed, module not removed.\n");
  690.         return res;
  691.     }
  692.     
  693.  
  694.     return 0;
  695. }
  696.  
  697.  
  698. EXPORT_NO_SYMBOLS;
  699. MODULE_PARM(debug, "i");
  700.  
  701.  
  702. MODULE_PARM_DESC(debug,
  703.        "debug level - 0 off; 1 normal; 2 verbose; ");
  704.  
  705. #ifdef MODULE
  706. MODULE_AUTHOR("Cherry George Mathew <cherry@freeshell.org>");
  707. MODULE_DESCRIPTION("i2c driver for the micronas vpx322xd 
  708.                     video processor family");
  709. MODULE_LICENSE("GPL");
  710.  
  711.  
  712. int init_module(void)
  713. {
  714.     return vpx_init();
  715. }
  716.  
  717.  
  718. int cleanup_module(void)
  719. {
  720.     return vpx_cleanup();
  721. }
  722.  
  723. #endif                        /* MODULE */
  724.  
  725.  
  726.  
  727.  
  728. /*
  729.  * Overrides for Emacs so that we follow Linus's tabbing style.
  730.  * ---------------------------------------------------------------------------
  731.  * Local variables:
  732.  * c-basic-offset: 8
  733.  * End:
  734.  */
  735.  
  736.  
  737.  
  738.  
  739.